package service

import (
	"errors"
	"gitee.com/llqhz/go-micro-user/user/domain/model"
	"gitee.com/llqhz/go-micro-user/user/domain/repository"
	"golang.org/x/crypto/bcrypt"
)

type IUserService interface {
	AddUser(user *model.User) (int64, error)
	DeleteUser(id int64) error
	UpdateUser(user *model.User, isChangePwd bool) error
	FindUserByName(name string) (*model.User, error)
	CheckPwd(name string, pwd string) (isOk bool, err error)
}

type UserService struct {
	// interface 本身可以传指针和非指针的值
	UserRepository repository.IUserRepository
}

func NewUserService(userRepository repository.IUserRepository) IUserService {
	return &UserService{UserRepository: userRepository}
}

// GeneratePassword
// @Description: 加密用户密码
// @param password string
// @return []byte
// @return error
func GeneratePassword(password string) ([]byte, error) {
	return bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
}

func ValidatePassword(password string, hashed string) (isOk bool, err error) {
	if err := bcrypt.CompareHashAndPassword([]byte(hashed), []byte(password)); err != nil {
		return false, errors.New("密码错误")
	}
	return true, nil
}

func (u UserService) AddUser(user *model.User) (int64, error) {
	// 加密密码, 插入数据, 返回结果
	hashed, err := GeneratePassword(user.HashPassword)
	if err != nil {
		return user.ID, err
	}
	user.HashPassword = string(hashed)

	return u.UserRepository.CreateUser(user)
}

func (u UserService) DeleteUser(id int64) error {
	// 删除用户, 返回结果
	return u.UserRepository.DeleteUserById(id)
}

func (u UserService) UpdateUser(user *model.User, isChangePwd bool) error {
	if isChangePwd {
		if hashed, err := GeneratePassword(user.HashPassword); err != nil {
			return err
		} else {
			user.HashPassword = string(hashed)
		}
	}
	return u.UserRepository.UpdateUser(user)
}

func (u UserService) FindUserByName(name string) (*model.User, error) {
	return u.UserRepository.FindUserByName(name)
}

func (u UserService) CheckPwd(name string, passwd string) (isOk bool, err error) {
	// 查用户, 比密码, 返回结果
	user, err := u.UserRepository.FindUserByName(name)
	if err != nil {
		return false, err
	}

	return ValidatePassword(passwd, user.HashPassword)
}
